#include "ioapi.hpp"
#include "commtick.hpp"
#include "app_config.h"
#include "variable.hpp"
///>IO 操作函数，调用底层GOIO 库
using namespace device;

#define IOAPI_SWITCH_FILTE		10

typedef struct
{
	uint8_t ucLedRed;
	uint8_t ucLedGreen;
	uint8_t ucLedYellow;
	uint16_t usTrip;
}IoProcessTPDF;

static IoProcessTPDF mIoProcess = {0};

/** 
 * @brief       滴答时钟
 * @retval      是否重载
 */
static bool IoApiTicked(void)
{
	static uint16_t i = 0;
	if(mIoProcess.usTrip)
	{
		mIoProcess.usTrip--;
		if(!mIoProcess.usTrip)
		{
			gpio::Write(APP_TRIP_PORT, APP_TRIP_PIN, 0);
		}
	}	
	if(mIoProcess.ucLedGreen == 0)
	{
		gpio::Write(APP_LED_GREEN_PORT, APP_LED_GREEN_PIN, 0);
	}
	else if(mIoProcess.ucLedGreen == 1)
	{
		gpio::Write(APP_LED_GREEN_PORT, APP_LED_GREEN_PIN, 1);
	}
	if(mIoProcess.ucLedRed == 0)
	{
		gpio::Write(APP_LED_RED_PORT, APP_LED_RED_PIN, 0);
	}
	else if(mIoProcess.ucLedRed == 1)
	{
		gpio::Write(APP_LED_RED_PORT, APP_LED_RED_PIN, 1);
	}
	if(mIoProcess.ucLedYellow == 0)
	{
		gpio::Write(APP_LED_YELLOW_PORT, APP_LED_YELLOW_PIN, 0);
	}
	else if(mIoProcess.ucLedYellow == 1)
	{
		gpio::Write(APP_LED_YELLOW_PORT, APP_LED_YELLOW_PIN, 1);
	}
	i++;
	if(i >= 1000)
	{
		i = 0;
		if(mIoProcess.ucLedGreen == 2)
		{
			gpio::Toggle(APP_LED_GREEN_PORT, APP_LED_GREEN_PIN);
		}
		if(mIoProcess.ucLedRed == 2)
		{
			gpio::Toggle(APP_LED_RED_PORT, APP_LED_RED_PIN);
		}
		if(mIoProcess.ucLedYellow == 2)
		{
			gpio::Toggle(APP_LED_YELLOW_PORT, APP_LED_YELLOW_PIN);
		}
	}
	return(true);
}

/** 
 * @brief       指示灯输出
 * @param[in]   tLedOutput 指示灯状态
 * @retval       None
 */
void IoApiLedOutput(LedOutputTPDF tLedOutput)
{
	switch(tLedOutput)
	{
		case LED_OUTPUT_GREEN_FLASH:
		case LED_OUTPUT_GREEN_OFF:
		case LED_OUTPUT_GREEN_ON:
			mIoProcess.ucLedGreen = tLedOutput & 0x0f;
			break;
		case LED_OUTPUT_RED_FLASH:
		case LED_OUTPUT_RED_OFF:
		case LED_OUTPUT_RED_ON:
			mIoProcess.ucLedRed = tLedOutput & 0x0f;
			break;
		case LED_OUTPUT_YELLOW_FLASH:
		case LED_OUTPUT_YELLOW_OFF:
		case LED_OUTPUT_YELLOW_ON:
			mIoProcess.ucLedYellow = tLedOutput & 0x0f;
			break;
		default:
			break;
	}
}

/** 
 * @brief       脱扣
 * @retval       None
 */
void IoApiTrip(void)
{
	gpio::Write(APP_TRIP_PORT, APP_TRIP_PIN, 1);
	mIoProcess.usTrip = 7;
}

/** 
 * @brief       初始化
 * @retval       None
 */
void IoApiInit(void)
{
	if(_PRODUCT_ATTRIBUTE & CONFIG_ATTRIBUTE_FLAG_SWITCH)
	{
		gpio::SetInputMode(gpio::GPIO_PORT_B, 0, false,false);
		gpio::SetInputMode(gpio::GPIO_PORT_B, 5, false,false);
		gpio::SetInputMode(gpio::GPIO_PORT_B, 6, false,false);
		gpio::SetInputMode(gpio::GPIO_PORT_B, 7, false,false);
		gpio::SetInputMode(gpio::GPIO_PORT_B, 8, false,false);
		gpio::SetInputMode(gpio::GPIO_PORT_B, 9, false,false);
		gpio::SetInputMode(gpio::GPIO_PORT_D, 3, false,false);
		gpio::SetInputMode(gpio::GPIO_PORT_D, 4, false,false);
		gpio::SetInputMode(gpio::GPIO_PORT_D, 5, false,false);
		gpio::SetInputMode(gpio::GPIO_PORT_D, 6, false,false);
		gpio::SetInputMode(gpio::GPIO_PORT_D, 7, false,false);
		gpio::SetInputMode(gpio::GPIO_PORT_D, 8, false,false);
		gpio::SetInputMode(gpio::GPIO_PORT_E, 7, false,false);
		gpio::SetInputMode(gpio::GPIO_PORT_E, 9, false,false);
		gpio::SetInputMode(gpio::GPIO_PORT_E, 10, false,false);
		IoApiSwitchUpdate();
	}
	commtick::RegisteTick(IoApiTicked, 1);
}

/** 
 * @brief       获取掉电信号
 * @retval      是否发生掉电
 */
extern bool IoApiPwdCheck(void)
{
	return(false);
}

/** 
 * @brief       更新拨码值,需要实时更新
 * @retval      None
 */
extern void IoApiSwitchUpdate(void)
{
	const uint32_t IrTbl_dis[] = {40,50,60,70,80,90,95,100};
	const uint32_t IrTbl_motor[] = {0,40,50,60,70,80,90,100};
	const uint32_t TrTbl_dis[] = {3,6,12,18};
	const uint32_t TrTbl_motor[] = {5,10,20,30};
	
	const uint32_t IsdTbl_dis[] = {0,15,20,30,40,60,80,100};
	const uint32_t IsdTbl_motor[] = {0,50,60,80,90,100,110,120};
	const uint32_t TsdTbl_dis[] = {100,200,300,400};
	
	const uint32_t IiTbl_dis[] = {0,2,3,4,6,8,10,12};
	
	const uint32_t InTbl[] = {0,5,10,0};
	
	const uint32_t IumbTbl[] = {0,30,40,50,60,70,80,90};
	const uint32_t TumbTbl[] = {4,6,8,10};
	
	uint8_t ucTbl[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
	uint8_t ucSwtTbl[6];
	uint8_t i;
	uint32_t j;
	
	for(i = 0; i < IOAPI_SWITCH_FILTE; i++)
	{
		j = gpio::Read(gpio::GPIO_PORT_B);
		if(j & (1 << 7)) { ucTbl[3]++; }
		if(j & (1 << 5)) { ucTbl[9]++; }
		if(j & (1 << 6)) { ucTbl[10]++; }
		if(j & (1 << 9)) { ucTbl[11]++; }
		if(j & (1 << 0)) { ucTbl[12]++; }
		if(j & (1 << 8)) { ucTbl[14]++; }
		j = gpio::Read(gpio::GPIO_PORT_D);
		if(j & (1 << 3)) { ucTbl[0]++; }
		if(j & (1 << 4)) { ucTbl[1]++; }
		if(j & (1 << 5)) { ucTbl[2]++; }
		if(j & (1 << 8)) { ucTbl[4]++; }
		if(j & (1 << 7)) { ucTbl[5]++; }
		if(j & (1 << 6)) { ucTbl[13]++; }
		j = gpio::Read(gpio::GPIO_PORT_E);
		if(j & (1 << 9)) { ucTbl[6]++; }
		if(j & (1 << 7)) { ucTbl[7]++; }
		if(j & (1 << 10)) { ucTbl[8]++; }
	}
	ucSwtTbl[0] = (ucTbl[0] > (IOAPI_SWITCH_FILTE - 2)? 0:4) | (ucTbl[1] > (IOAPI_SWITCH_FILTE - 2)? 0:2) | (ucTbl[2] > (IOAPI_SWITCH_FILTE - 2)? 0:1);
	ucSwtTbl[1] = (ucTbl[3] > (IOAPI_SWITCH_FILTE - 2)? 0:4) | (ucTbl[4] > (IOAPI_SWITCH_FILTE - 2)? 0:2) | (ucTbl[5] > (IOAPI_SWITCH_FILTE - 2)? 0:1);
	ucSwtTbl[2] = (ucTbl[6] > (IOAPI_SWITCH_FILTE - 2)? 0:4) | (ucTbl[7] > (IOAPI_SWITCH_FILTE - 2)? 0:2) | (ucTbl[8] > (IOAPI_SWITCH_FILTE - 2)? 0:1);
	ucSwtTbl[3] = (ucTbl[9] > (IOAPI_SWITCH_FILTE - 2)? 0:2) | (ucTbl[10] > (IOAPI_SWITCH_FILTE - 2)? 0:1);
	ucSwtTbl[4] = (ucTbl[11] > (IOAPI_SWITCH_FILTE - 2)? 0:2) | (ucTbl[12] > (IOAPI_SWITCH_FILTE - 2)? 0:1);
	ucSwtTbl[5] = (ucTbl[13] > (IOAPI_SWITCH_FILTE - 2)? 0:2) | (ucTbl[14] > (IOAPI_SWITCH_FILTE - 2)? 0:1);
	if(_PRODUCT_ATTRIBUTE & CONFIG_ATTRIBUTE_FLAG_MOTOR)
	{
		_SWITCH_CONFIG.usLongDelayCurrent = IrTbl_motor[ucSwtTbl[0]] * _PRODUCT_RATEDCURRENT / 100;
		_SWITCH_CONFIG.usLongDelayTime = TrTbl_motor[ucSwtTbl[4]];
		_SWITCH_CONFIG.usShortDelayCurrent = IsdTbl_motor[ucSwtTbl[2]];
		_SWITCH_CONFIG.usShortDelayTime = 100;
		_SWITCH_CONFIG.usShortCircuitCurrent = 15;
		_SWITCH_CONFIG.usUnbalanceRated = IumbTbl[ucSwtTbl[1]];
		_SWITCH_CONFIG.usUnbalanceTime = TumbTbl[ucSwtTbl[5]];
		_SWITCH_CONFIG.usNCurrent = InTbl[ucSwtTbl[3]];
	}
	else
	{
		_SWITCH_CONFIG.usLongDelayCurrent = IrTbl_dis[ucSwtTbl[0]] * _PRODUCT_RATEDCURRENT / 100;
		_SWITCH_CONFIG.usLongDelayTime = TrTbl_dis[ucSwtTbl[4]];
		_SWITCH_CONFIG.usShortDelayCurrent = IsdTbl_dis[ucSwtTbl[1]];
		_SWITCH_CONFIG.usShortDelayTime = TsdTbl_dis[ucSwtTbl[5]];
		_SWITCH_CONFIG.usShortCircuitCurrent = IiTbl_dis[ucSwtTbl[2]];
		_SWITCH_CONFIG.usNCurrent = InTbl[ucSwtTbl[3]];
	}
}
